Een Controller klasse maken
Home

Een Controller klasse maken

Een Controller klasse maken

Knoppen staan op formulieren, al een geluk. Maar de code, die de interactie met de gebruiker afhandelt, staat heel dikwijls overal versnipperd. Heel wat redirects waarmee je van her naar der springt. Redirects raad ik af want moeilijk te debuggen. De afhandeling van de interactie staat waarlijk overal en nergens. Hoe kan je in godsnaam de workflow volgen? Is het geen idee om alle interactie met de gebruiker op één plaats te centraliseren in wat in het MVC patroon, de controller wordt genoemd?

  1. We maken één enkele routing switch die alle interactie met de gebruiker afhandelt.
  2. We gebruiken reflectie om de klasse te instantiëren en de methode uit te voeren

Masterpage

De website heeft slechts één pagina, namelijk index.php, die in de root van de website staat. Dat maakt het navigeren overzichtelijker en het onderhouden van de verschillende views binnen de website gemakkelijker.

Use cases

Een volgende stap is het opstellen van use cases. Je gaat zien dat met elke use case een knop overeenstemt. Ik heb het niet over systeem use cases maar over gebruikers use cases. We hebben een manier nodig om use cases een naam te geven. Daarvoor laten we ons inspireren door REST. Een use case bestaat uit

  1. de namespace waarin de entiteit zich bevindt;
  2. de naam van de entiteit (object/klasse);
  3. de naam van de actiemethode;
  4. een id parameter;

De drie elementen worden gescheiden door een schuine streep /.

Voorbeelden:

De naam van de entiteit is de naam van de controller en de naam van de actie is de naam van de methode van de controller die moet worden uitgevoerd.

Routing regels

  1. 1 element: de naam verwijst naar een controller klasse in de standaard namespace;
  2. 2 elementen: de eerste naam verwijst naar de controller klasse in de standaard namespace en de tweede naar de methode;
  3. 3 of meer elementen:
    1. is het laatste element numeriek dan verwijst alles wat voor het derdelaatste element komt naar de namespace, het derdelaatste element naar de controller klasse in de standaard namespace, de tweedelaatste naar de methode en de laatste is de parameter waarde; is er geen namespace opgegeven wordt de standaard namespace gebruikt;
    2. is het laatste element niet numeriek dan is het derdelaatste element en alles wat er voor komt de namespace, het tweede de controller en het derde de methode;

MVC URL Pattern with namespace
MVC URL Pattern with namespace

Code voor dispatcher

We schrijven een methode in het bestand index.php, die de URL analyseert en in betekenisvolle onderdelen opbreekt:

<?php
function dispatchPlus($route, $defaultNamespace = '/') {
    // remove first /, if present
    $route = ltrim($route, '/');
    $routeParts = explode('/', $route);
    $namespaceName = $defaultNamespace;
    $countRouteParts = count($routeParts);
    if ($countRouteParts === 1) {
        // klassenamen in PHP beginnen met een hoofdletter, pascalnotatie
        $controllerName = ucfirst($routeParts[0]);
        // functies in camelcasenotatie
        $actionMethodName = 'index';
        $parameterValue = -1;  
    } elseif ($countRouteParts === 2) {
        $controllerName = ucfirst($routeParts[0]);
        $actionMethodName = lcfirst($routeParts[1]);
        $parameterValue = -1;  
    } else {
        if (is_numeric(end($routeParts))) {
            $controllerName = ucfirst($routeParts[$countRouteParts - 3]);
            $actionMethodName = lcfirst($routeParts[$countRouteParts - 2]);
            $parameterValue = $routeParts[$countRouteParts - 1];  
        } else {
            $namespaceName = ucfirst($routeParts[$countRouteParts - 3]);
            $controllerName = ucfirst($routeParts[$countRouteParts - 2]);
            $actionMethodName = lcfirst($routeParts[$countRouteParts - 1]);
            $parameterValue = -1;  
        }
        if (count($routeParts) > 3) {
            $path = implode('/', array_map('ucfirst',
                array_slice($routeParts, 0, $countRouteParts - 3)));
            $namespaceName = $path . '/' . $namespaceName;
        }
    }
   
    echo '<p>Namespacenaam: ' . $namespaceName . '</p>';
    echo '<p>Controllernaam: ' . $controllerName . '</p>';
    echo '<p>Actiemethodenaam: ' . $actionMethodName . '</p>';
    echo '<p>Parameter waarde: ' . $parameterValue . '</p>';
}

if (isset($_SERVER['REDIRECT_URL'])) {
    dispatchPlus($_SERVER['REDIRECT_URL']);
}

Om de code te testen moet die staan in index.php. Deze code staat in mijn workspace op Cloud9 in het bestand met de naam index-prepare-controller.php.

Let op het gebruik van:

  1. implode retourneert een string die bestaat alle elementen van de opgegeven array gescheiden door de opgegeven scheidingstekenreeks.
  2. array_slice om een deel van een opgegeven array, te kopiëren en te retourneren, te beginnen van een opgegeven startelement tot een opgegeven eindelement;
  3. array_map doorloopt alle elementen van de array en voort de functie die als eerste argument wordt meegegeven op elk element uit en retourneert het resultaat;

Refactoring

  1. Ontwerp

    Het wordt tijd om de procedurale werkwijze te verlaten en OO te beginnen werken. We gaan een klasse maken met de naam Controller. Deze klasse zetten we in een namespace die naam van de vendor en van het product bevat. In dit geval is ModernWays. ModernWays is de naam van het bedrijf dat het product maakt.

    We kiezen ervoor om een static klasse met static members te maken. Dan moeten we geen instantie van de klasse maken vooraleer die te gebruiken en we beschikken tegelijkertijd over een singleton klasse.

    Controller klasse
    Members Naam Scope Beschrijnving
    velden $namespaceName public
    $controllerName public
    $actionMethodName public
    $parameterValue public
    methoden dispatch public breekt de url op in een controllernaam, actiemethode en parameter waarde
    dispatchPlus public breekt de url op in een namespacenaam, controllernaam, actiemethode en parameter waarde
  2. Mappenstructuur
    We bereiden ons voor op het gebruik van Composer, een packagemanager voor PHP, en plaatsen onze klassen in een mappenstructuur zoals vereist:
    |vendor
        |modernways
            |src
                |Controller.php
  3. De dispatcher toevoegen

    Je gebruikt DispatchPlus als je een namespace op de url wil meegeven.

    <?php
    /**
     * Created by ModernWays
     * User: Jef Inghelbrecht
     * Date: 10/04/2019
     * Time: 10:32
     */
    namespace ModernWays;
    
    // tussen de declaratie van de namespace en de rest 1 lege regel.
    class Controller
    {
        static public $namespaceName;
        static public $controllerName;
        static public $actionMethodName;
        static public $parameterValue;
        
    
        /**
         * breekt de url op in een controllernaam, actiemethode en
         * parameter waarde
         * @param null $route
         * @return string
         */
         public static function dispatch($route, $defaultNamespace = '/') {
            self::$namespaceName = $defaultNamespace; 
            self::$controllerName = 'Home';
            self::$actionMethodName = 'index';
            self::$parameterValue = -1;// Standard parameter. Shouldn't appear in the database.    // remove first /, if present
            $route = ltrim($route, '/');
            $routeParts = explode('/', $route);
            if  (isset($routeParts[0])) {
                // klassenamen in PHP beginnen met een hoofdletter, pascalnotatie
                self::$controllerName = ucfirst($routeParts[0]);
            }
            if (isset($routeParts[1])) {
                // functies in camelcasenotatie
                self::$actionMethodName = lcfirst($routeParts[1]);
            }
            if (isset($routeParts[2])) {
                self::$parameterValue = $routeParts[2];
            }
            
            return '<p>Controllernaam: ' . self::$controllerName . '</p>' .
                '<p>Actiemethodenaam: ' . self::$actionMethodName . '</p>' .
                 '<p>Parameter waarde: ' . self::$parameterValue . '</p>';
        }
    
        /**
         * breekt de url op in een namespacenaam, controllernaam,
         * actiemethode en parameter waarde
         * @param route
         * @param $defaultNamespace
         * @return string
         */    
         function dispatchPlus($route, $defaultNamespace = '/') {
            // remove first /, if present
            $route = ltrim($route, '/');
            $routeParts = explode('/', $route);
            self::$namespaceName = $defaultNamespace;
            $countRouteParts = count($routeParts);
            if ($countRouteParts === 1) {
                // klassenamen in PHP beginnen met een hoofdletter, pascalnotatie
                self::$controllerName = ucfirst($routeParts[0]);
                // functies in camelcasenotatie
                self::$actionMethodName = 'index';
                self::$parameterValue = -1;  
            } elseif ($countRouteParts === 2) {
                self::$controllerName = ucfirst($routeParts[0]);
                self::$actionMethodName = lcfirst($routeParts[1]);
                self::$parameterValue = -1;  
            } else {
                if (is_numeric(end($routeParts))) {
                    self::$controllerName = ucfirst($routeParts[$countRouteParts - 3]);
                    self::$actionMethodName = lcfirst($routeParts[$countRouteParts - 2]);
                    self::$parameterValue = $routeParts[$countRouteParts - 1];  
                } else {
                    self::$namespaceName = ucfirst($routeParts[$countRouteParts - 3]);
                    self::$controllerName = ucfirst($routeParts[$countRouteParts - 2]);
                    self::$actionMethodName = lcfirst($routeParts[$countRouteParts - 1]);
                    self::$parameterValue = -1;  
                }
                if (count($routeParts) > 3) {
                    $path = implode('/', array_map('ucfirst',
                        array_slice($routeParts, 0, $countRouteParts - 3)));
                    self::$namespaceName = $path . '/' . self::$namespaceName;
                }
            }
           
            return '<p>Namespacenaam: ' . self::$namespaceName . '</p>' .
                '<p>Controllernaam: ' . self::$controllerName . '</p>' .
                '<p>Actiemethodenaam: ' . self::$actionMethodName . '</p>' .
                '<p>Parameter waarde: ' . self::$parameterValue . '</p>';
        }
    }
  4. De klasse testen

    Kopiëer wat er in index.php staat naar index-prepare-controller.php. We gaan de index.php pagina nu gebruiken om de Controller klasse uit te proberen.
    We beginnen met het Controller.php bestand in te sluiten met de include instructie:

    <?php
    include ('vendor/modernways/src/Controller.php');
    
    $redirectUrl = 'Home/index';
    $namespaceName = 'ModernWays';
    if (isset($_SERVER['REDIRECT_URL'])) {
        $redirectUrl = $_SERVER['REDIRECT_URL'];
    }
    echo '<h1>Resultaat Dispatch:</h1>';
    echo ModernWays\Controller::dispatch($redirectUrl);
    echo '<h1>Resultaat DispatchPlus:</h1>';
    echo ModernWays\Controller::dispatchPlus($redirectUrl, $namespaceName);
  5. Resultaat
    PHP MVC Test Controller 1
    PHP MVC Test Controller 1
  6. De actiemethode uitvoeren

    De dispatcher heeft de naam van de controller en van de actiemethode uit de url gefilterd. We gaan reflection gebruiken om een de methode van de controllerklasse uit te voeren.

    Voeg de volgende methode aan de Controller klasse toe:

    /**
     * Creates an instance of itself with the name passed in $entity
     * and invokes the method with the name passed in $action
     * @return bool|mixed
     */
    public static function invokeAction()
    {
        // Functions, method calls, static class variables, and class constants inside {$} work since PHP 5.
        // However, the value accessed will be interpreted as the name of a variable in the scope in which the
        // string is defined. Using single curly braces ({}) will not work for accessing the return values of
        // functions or methods or the values of class constants or static class variables.
        $namespaceName = self::$namespaceName;
        $controllerName = self::$controllerName;
        $actionMethodName = self::$actionMethodName;
        $id = self::$parameterValue;
        $controllerName = "\\{$namespaceName}\\Controllers\\{$controllerName}Controller";
        $actionMethod = new \ReflectionMethod($controllerName, $actionMethodName);
        if (!class_exists($controllerName, true)) {
            return false;
        } else {
            $reflection = new \ReflectionClass($controllerName);
            $controller = $reflection->newInstance();
            return $actionMethod->invokeArgs($controller, array($id));
        }
    }
    
  7. Een Controller klasse maken voor Student

    We gaan de Controller klasse nu toepassen. We maken een StudentController klasse die overerft van de Controller klasse. In deze klasse maken we een methode met de naam readingAll die alle studenten oplijst. Volgens de afspraak - we volgen de afspraken van ASP.NET MVC - staan de controllers in een map met de naam Controllers.

    Het model is hier een gewone array. Later zien we hoe de controller het model opvult vanuit een database.
    Plaats de code in een bestand met de naam /Controllers/StudentController.php:

    <?php
    /**
     * Created by ModernWays
     * User: Jef Inghelbrecht
     * Date: 10/04/2019
     * Time: 10:32
     */
    namespace ModernWays\Controllers;
    
    class StudentController extends \ModernWays\Controller
    {
        // het model vullen we later met een DAL
        private $student = array('Jef Inghelbrecht',
            'Kees Baaten',
            'Liesbeth Baaten',
            'Mohammed El Farisi');
            
        public function readingAll() {
            echo '<h1>Studenten</h1>' .
                    '<table>' .
                    '<caption>Studenten</caption>' .
                    '<tr>' .
                    '<th>Naam</th>' .
                    '</tr>';
            for ($i = 0; $i < count($model); $i++) {
                echo '<tr><td>' . $model[$i] . '</td></tr>';
            }
        }
    }
  8. De StudentController klasse testen
    1. We beginnen met de Controller.php en StudentController.php bestanden in te sluiten met de include instructie.
      In de index.php pagina typ je het volgende:
      <?php
      include ('vendor/modernways/src/Controller.php');
      include ('Controllers/StudentController.php');
      
      if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
          setlocale(LC_ALL, 'nld_nld');
      } else {
          setlocale(LC_ALL, 'nlb');
      }
      
      $redirectUrl = 'Home/index';
      if (isset($_SERVER['REDIRECT_URL'])) {
          $redirectUrl = $_SERVER['REDIRECT_URL'];
      }
      ModernWays\Controller::dispatchPlus($redirectUrl, 'ModernWays');
      ModernWays\Controller::invokeAction();
    2. in de url typ je:
      https://programmeren4-16570-jef-jefinghelbrecht.c9users.io/Student/ReadingAll
    3. Met dit als resultaat:
      PHP MVC Test Controller 2
      PHP MVC Test Controller 2
  9. De View implementeren

    De controller is de koppeling tussen de gebruikersinterface (view) en de verwerkingslogica (model). De controller gebruikt de modelmethoden voor het ophalen van informatie over het applicatie-object (ding, entiteit) of voor het wijzigen van de status van het object. De controller informeert vervolgens de view over de wijzigingen.

    We gaan nu leren hoe de controller de view kan informeren over de wijzigingen.

    1. De view methode

      In de Controller klasse voegen we en methode toe die de view retourneert die aan de gebruiker moet worden getoond.

      We moeten het model, dat in de controller wordt bijgewerkt, en het pad waar de view zich bevindt aan de View meegeven. We moeten dus de data bewaren tot het moment dat de view functie wordt uitgevoerd. Dat doen we met behulp van een PHP closure.

      public static function view($model = null, $path = null) {
          // als het pad naar de view niet werd opgegeven en dus null is,
          // staat het in een submap met de naam Views en heeft het
          //
          if (!isset($path)) {
              $trace = debug_backtrace();
              // echo '<pre>' . var_dump($trace) . '</pre>';
              $method = ucfirst($trace[1]["function"]);
              $class = $trace[1]["class"];
              $class = substr($class, strrpos($class, '\\') + 1);
              $class = str_replace('Controller', '', $class);
              $path = "Views/{$class}/{$method}.php";
          }
          $view = function () use ($model, $path) {
              include($path);
          };
          return $view;
      }
    2. De view zelf
      De view zelf is een php bestand dat volgens de afspraken binnen ASP.NET MVC in een map met de naam Views staat. In deze map moet een submap met dezelfde naam als de controller staan. In dit geval hier is dat Student. En in de Studentmap een php bestand met dezelfde naam als de actiemethode van de controller. In ons voorbeeld is dat ReadingAllWithView:
      PHP MVC Directory Structure 2
      PHP MVC Directory Structure 2
    3. De code in ReadingAllWithView.php:
      <h1>Studenten</h1>
      <table>
          <caption>Studenten</caption>
          <tr>
              <th>Naam</th>
          </tr>
      <?php
          for ($i = 0; $i < count($model); $i++) {
      ?>
          <tr>
              <td><?php echo $model[$i];?></td>
          </tr>
      <?php
          }
      ?>
      </table>
    4. De view methode gebruiken

      Als de gebruiker de volgende url intypt

      https://programmeren4-16570-jef-jefinghelbrecht.c9users.io/Student/ReadingAllWithView

      dan moet de controller met de naam StudentController geïnstancieerd worden en de methode met de naam readingAllWithView uitgevoerd worden. Standaard retourneert deze methode een view met de naam Views/Student/ReadingAllWithView.php:

      public function readingAllWithView() {
          return $this->view($this->student);
      }

      Wil je een view met een andere naam weergeven moet je het volledige pad opgeven. Neem aan dat je view als naam ReadingAllWithTileView.php heeft dan moet je het volgende pad meegeven:

      public function readingAllWithView() {
          return $this->view($this->student, 
              'Views/Student/ReadingAllWithTileView.php');
      }
    5. De StudentController klasse testen met view

      De index.php pagina passen we aan om de view methode te kunnen gebruiken. Let erop dat we aan de view methode gaan pad naar de view meegeven omdat die in de standaard map staat, namelijk Views/Controllernaam/ActionMethod.php:

      <?php
      include ('vendor/modernways/src/Controller.php');
      include ('Controllers/StudentController.php');
      
      $redirectUrl = 'Home/index';
      if (isset($_SERVER['REDIRECT_URL'])) {
          $redirectUrl = $_SERVER['REDIRECT_URL'];
      }
      ModernWays\Controller::dispatchPlus($redirectUrl, 'ModernWays');
      $view = ModernWays\Controller::invokeAction();
      ?>
      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <meta http-equiv="X-UA-Compatible" content="ie=edge">
          <title>PHP MVC</title>
      </head>
      <body>
          <?php $view(); ?>
      </body>
      </html>
      

      Met de methode dispatchPlus breken we de url op in betekenisvolle onderdelen. De methode invokeAction maakt een instantie van de controllerklasse en voert de methode uit die in de url werden opgegeven. De invokeAction methode retourneert de view die in het browservenster zal worden getoond:

      <body>
          <?php $view(); ?>
      </body>
      

De volledige code

  1. vendor/modernways/src/Controller.php
    <?php
    /**
     * Created by ModernWays
     * User: Jef Inghelbrecht
     * Date: 10/04/2019
     * Time: 10:32
     */
    namespace ModernWays;
    
    // tussen de declaratie van de namespace en de rest 1 lege regel.
    class Controller
    {
        static public $namespaceName;
        static public $controllerName;
        static public $actionMethodName;
        static public $parameterValue;
        
        /**
         * breekt de url op in een controllernaam, actiemethode en
         * parameter waarde
         * @param null $route
         * @return string
         */
         public static function dispatch($route, $defaultNamespace = '/') {
            self::$namespaceName = $defaultNamespace;
            self::$controllerName = 'Home';
            self::$actionMethodName = 'index';
            self::$parameterValue = -1;// Standard parameter. Shouldn't appear in the database.    // remove first /, if present
            $route = ltrim($route, '/');
            $routeParts = explode('/', $route);
            if  (isset($routeParts[0])) {
                // klassenamen in PHP beginnen met een hoofdletter, pascalnotatie
                self::$controllerName = ucfirst($routeParts[0]);
            }
            if (isset($routeParts[1])) {
                // functies in camelcasenotatie
                self::$actionMethodName = lcfirst($routeParts[1]);
            }
            if (isset($routeParts[2])) {
                self::$parameterValue = $routeParts[2];
            }
            
            return '<p>Controllernaam: ' . self::$controllerName . '</p>' .
                '<p>Actiemethodenaam: ' . self::$actionMethodName . '</p>' .
                 '<p>Parameter waarde: ' . self::$parameterValue . '</p>';
        }
    
        /**
         * breekt de url op in een namespacenaam, controllernaam,
         * actiemethode en parameter waarde
         * @param route
         * @param $defaultNamespace
         * @return string
         */    
         function dispatchPlus($route, $defaultNamespace = '/') {
            // remove first /, if present
            $route = ltrim($route, '/');
            $routeParts = explode('/', $route);
            self::$namespaceName = $defaultNamespace;
            $countRouteParts = count($routeParts);
            if ($countRouteParts === 1) {
                // klassenamen in PHP beginnen met een hoofdletter, pascalnotatie
                self::$controllerName = ucfirst($routeParts[0]);
                // functies in camelcasenotatie
                self::$actionMethodName = 'index';
                self::$parameterValue = -1;  
            } elseif ($countRouteParts === 2) {
                self::$controllerName = ucfirst($routeParts[0]);
                self::$actionMethodName = lcfirst($routeParts[1]);
                self::$parameterValue = -1;  
            } else {
                if (is_numeric(end($routeParts))) {
                    self::$controllerName = ucfirst($routeParts[$countRouteParts - 3]);
                    self::$actionMethodName = lcfirst($routeParts[$countRouteParts - 2]);
                    self::$parameterValue = $routeParts[$countRouteParts - 1];  
                } else {
                    self::$namespaceName = ucfirst($routeParts[$countRouteParts - 3]);
                    self::$controllerName = ucfirst($routeParts[$countRouteParts - 2]);
                    self::$actionMethodName = lcfirst($routeParts[$countRouteParts - 1]);
                    self::$parameterValue = -1;  
                }
                if (count($routeParts) > 3) {
                    $path = implode('/', array_map('ucfirst',
                        array_slice($routeParts, 0, $countRouteParts - 3)));
                    self::$namespaceName = $path . '/' . self::$namespaceName;
                }
            }
           
            return '<p>Namespacenaam: ' . self::$namespaceName . '</p>' .
                '<p>Controllernaam: ' . self::$controllerName . '</p>' .
                '<p>Actiemethodenaam: ' . self::$actionMethodName . '</p>' .
                '<p>Parameter waarde: ' . self::$parameterValue . '</p>';
        }
        
        /**
         * Creates an instance of itself with the name passed in $entity
         * and invokes the method with the name passed in $action
         * @return bool|mixed
         */
        public static function invokeAction()
        {
            // Functions, method calls, static class variables, and class constants inside {$} work since PHP 5.
            // However, the value accessed will be interpreted as the name of a variable in the scope in which the
            // string is defined. Using single curly braces ({}) will not work for accessing the return values of
            // functions or methods or the values of class constants or static class variables.
            $namespaceName = self::$namespaceName;
            $controllerName = self::$controllerName;
            $actionMethodName = self::$actionMethodName;
            $id = self::$parameterValue;
            $controllerName = "\\{$namespaceName}\\Controllers\\{$controllerName}Controller";
            $actionMethod = new \ReflectionMethod($controllerName, $actionMethodName);
            if (!class_exists($controllerName, true)) {
                return false;
            } else {
                $reflection = new \ReflectionClass($controllerName);
                $controller = $reflection->newInstance();
                return $actionMethod->invokeArgs($controller, array($id));
            }
        }
        
        public static function view($model = null, $path = null) {
            // als het pad naar de view niet werd opgegeven en dus null is,
            // staat het in een submap met de naam Views en heeft het
            //
            if (!isset($path)) {
                $trace = debug_backtrace();
                // echo '<pre>' . var_dump($trace) . '</pre>';
                $method = ucfirst($trace[1]["function"]);
                $class = $trace[1]["class"];
                $class = substr($class, strrpos($class, '\\') + 1);
                $class = str_replace('Controller', '', $class);
                $path = "Views/{$class}/{$method}.php";
            }
            $view = function () use ($model, $path) {
                include($path);
            };
            return $view;
        }
    }
    
    
  2. Controllers/StudentController.php
    <?php
    /**
     * Created by ModernWays
     * User: Jef Inghelbrecht
     * Date: 10/04/2019
     * Time: 10:32
     */
    namespace ModernWays\Controllers;
    
    class StudentController extends \ModernWays\Controller
    {
        // het model vullen we later met een DAL
        private $student = array('Jef Inghelbrecht',
            'Kees Baaten',
            'Liesbeth Baaten',
            'Mohammed El Farisi');
            
        public function readingAll() {
            $model = $this->student;
            echo '<h1>Studenten</h1>' .
                    '<table>' .
                    '<caption>Studenten</caption>' .
                    '<tr>' .
                    '<th>Naam</th>' .
                    '</tr>';
            for ($i = 0; $i < count($model); $i++) {
                echo '<tr><td>' . $model[$i] . '</td></tr>';
            }
        }
        
        public function readingAllWithView() {
            return $this->view($this->student);
        }
    }
  3. Views/Student/ReadingAllWithView.php
    <h1>Studenten</h1>
    <table>
        <caption>Studenten</caption>
        <tr>
            <th>Naam</th>
        </tr>
    <?php
        for ($i = 0; $i < count($model); $i++) {
    ?>
        <tr>
            <td><?php echo $model[$i];?></td>
        </tr>
    <?php
        }
    ?>
    </table>
  4. index.php
    <?php
    include ('vendor/modernways/src/Controller.php');
    include ('Controllers/StudentController.php');
    
    if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
        setlocale(LC_ALL, 'nld_nld');
    } else {
        setlocale(LC_ALL, 'nlb');
    }
    
    $redirectUrl = 'Home/index';
    if (isset($_SERVER['REDIRECT_URL'])) {
        $redirectUrl = $_SERVER['REDIRECT_URL'];
    }
    ModernWays\Controller::dispatchPlus($redirectUrl, 'ModernWays');
    $view = ModernWays\Controller::invokeAction();
    ?>
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>PHP MVC</title>
    </head>
    <body>
        <?php $view(); ?>
    </body>
    </html>


 
JI
2019-04-12 09:32:53